home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #2 / Ham Radio 2000 - Volume 2.iso / HAMV2 / TCP_IP / TNOS230S / UNIXASY.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-09-06  |  20.6 KB  |  934 lines

  1. #ifdef UNIX
  2. /*
  3.  * File stolen from WAMPES 921229, modified for compatibility with JNOS and my
  4.  * tastes, and left to sink or swim.  Blub!  ++bsa
  5.  *
  6.  * The actual structure is much closer to that of JNOS than to WAMPES.  The
  7.  * reason is that WAMPES uses these weirdball I/O hooks... We will use the
  8.  * "classic" interface, modified by the use of register_fd().  (Actually, the
  9.  * weirdball I/O hooks are just WAMPES's version of register_fd().  The API
  10.  * for WAMPES is a heck of a lot hairier, though.)
  11.  */
  12.  
  13. #include "global.h"
  14. #include "commands.h"
  15.  
  16. #include <fcntl.h>
  17. #include <termios.h>
  18. #include <sys/time.h>
  19. #include <sys/stat.h>
  20. #include <signal.h>
  21.  
  22. #ifdef UNIX_SOCKETS
  23. /* to prevent calling in "socket.h", "tcp.h", and "sockaddr.h" */
  24. #define    _SOCKET_H
  25. #define _TCP_H
  26. #define _SOCKADDR_H
  27. /*lint -save -e508 -e631 -e532 -e27 -e43 */
  28. #include <sys/socket.h>
  29. #include <netinet/in.h>
  30. #include <arpa/inet.h>
  31. #include <netdb.h>
  32. /*lint -restore */
  33. #endif
  34.  
  35. #include "mbuf.h"
  36. #include "proc.h"
  37. /*lint -save -e114 */
  38. #include "iface.h"
  39. /*lint -restore */
  40. #include "asy.h"
  41. #include "unixasy.h"
  42. /*lint -esym(762,select) */
  43. #include "hardware.h"
  44. #include "devparam.h"
  45. #include "kisspoll.h"
  46.  
  47. #if !defined(_lint)
  48. static char rcsid[] OPTIONAL = "$Id: unixasy.c,v 1.34 1997/09/07 00:31:16 root Exp root $";
  49. #endif
  50.  
  51. #ifndef EWOULDBLOCK
  52. #define EWOULDBLOCK EAGAIN
  53. #endif
  54.  
  55. #ifndef TNOS_CRTSCTS
  56. #define CRTSCTS      0x80000000UL
  57. #endif
  58.  
  59. char const *LOCKDIR = NULLCHAR;
  60.  
  61. static int find_speed (long speed);
  62. static void asy_tx (int, void *, void *);
  63. static void asy_input (int, void *, void *);
  64. static int asy_vmin (int dev, long pktsize);
  65. static int asy_rts (int dev, unsigned long onoff);
  66. void pasy (struct asy *asyp);
  67.  
  68. struct asy *Asy;    /* allocated in main.c */
  69.  
  70. /*---------------------------------------------------------------------------*/
  71.  
  72. static int dorxqueue (int argc, char **argv, void *p);
  73. static int dotxqueue (int argc, char **argv, void *p);
  74. static int dobufsize (int argc, char **argv, void *p);
  75. static int doasy2stat (int argc, char **argv, void *p);
  76.  
  77. static struct cmds AsyPcmds[] =
  78. {
  79.     { "rxqueue",    dorxqueue,    0, 0, NULLCHAR },
  80.     { "txqueue",    dotxqueue,    0, 0, NULLCHAR },
  81.     { "bufsize",    dobufsize,    0, 0, NULLCHAR },
  82.     { "status",    doasy2stat,    0, 0, NULLCHAR },
  83.     { NULLCHAR,    NULL,        0, 0, NULLCHAR }
  84. };
  85.  
  86. /*---------------------------------------------------------------------------*/
  87.  
  88. static struct {
  89.     long speed;
  90.     speed_t flags;
  91. } speed_table[] = {
  92. #ifdef B50
  93.     { 50, B50 },
  94. #endif
  95. #ifdef B75
  96.     { 75, B75 },
  97. #endif
  98. #ifdef B110
  99.     { 110, B110 },
  100. #endif
  101. #ifdef B134
  102.     { 134, B134 },
  103. #endif
  104. #ifdef B150
  105.     { 150, B150 },
  106. #endif
  107. #ifdef B200
  108.     { 200, B200 },
  109. #endif
  110. #ifdef B300
  111.     { 300, B300 },
  112. #endif
  113. #ifdef B600
  114.     { 600, B600 },
  115. #endif
  116. #ifdef B900
  117.     { 900, B900 },
  118. #endif
  119. #ifdef B1200
  120.     { 1200, B1200 },
  121. #endif
  122. #ifdef B1800
  123.     { 1800, B1800 },
  124. #endif
  125. #ifdef B2400
  126.     { 2400, B2400 },
  127. #endif
  128. #ifdef B3600
  129.     { 3600, B3600 },
  130. #endif
  131. #ifdef B4800
  132.     { 4800, B4800 },
  133. #endif
  134. #ifdef B7200
  135.     { 7200, B7200 },
  136. #endif
  137. #ifdef B9600
  138.     { 9600, B9600 },
  139. #endif
  140. #ifdef B19200
  141.     { 19200, B19200 },
  142. #endif
  143. #ifdef B38400
  144.     { 38400, B38400 },
  145. #endif
  146. #ifdef B57600
  147.     { 57600, B57600 },
  148. #endif
  149. #ifdef B115200
  150.     { 115200, B115200 },
  151. #endif
  152. #ifdef B230400
  153.     { 230400, B230400 },
  154. #endif
  155. #ifdef B460800
  156.     { 460800, B460800 },
  157. #endif
  158.     { -1, 0 }
  159. };
  160.  
  161.  
  162. /*---------------------------------------------------------------------------*/
  163.  
  164. static int
  165. find_speed (long speed)
  166. {
  167. int i;
  168.  
  169.     i = 0;
  170.     while (speed_table[i].speed < speed && speed_table[i + 1].speed > 0)
  171.         i++;
  172.     return i;
  173. }
  174.  
  175.  
  176. /*---------------------------------------------------------------------------*/
  177.  
  178.  
  179. int
  180. Unixlockfile (char const *name, int dev, char const *basename, int silent)
  181. {
  182. int k;
  183. int fd;
  184. int (*pf) (const char *fmt,...);
  185. #ifdef HAVE_BINARY_LOCKFILES
  186. int pid;
  187. #else
  188. char filename[80];
  189. #endif
  190.  
  191.     pf = (dev) ? tprintf : printf;
  192.     for (k = 0; k < 30; k++) {
  193.         if ((fd = open (name, O_WRONLY | O_CREAT | O_EXCL, 0644)) != -1 || errno != EEXIST)
  194.             break;
  195.         /* read pid, unlink and retry if proc no longer exists */
  196.         if ((fd = open (name, O_RDONLY)) == -1) {
  197.             (void) sleep (1);
  198.             continue;    /* timing is everything */
  199.         }
  200. #ifdef HAVE_BINARY_LOCKFILES
  201.         read (fd, &pid, sizeof (pid));
  202.         close (fd);
  203.         fd = pid;
  204. #else
  205.         filename[read (fd, filename, 10)] = '\0';
  206.         close (fd);
  207.         sscanf (filename, "%d", &fd);
  208. #endif
  209.         if (kill (fd, 0) == -1 && errno == ESRCH) {
  210.             if (!silent)
  211.                 (void) (*pf) ("Removing stale lockfile for %s\n", basename);
  212.             unlink (name);
  213.             continue;
  214.         }
  215.         (void) (*pf) ("%s%s is locked by process %d\n", (dev) ? "/dev/" : "", basename, fd);
  216.         return -1;
  217.     }
  218.     if (fd == -1) {
  219.         (void) (*pf) ("Can't lock %s%s: %s\n", (dev) ? "/dev/" : "", basename, strerror (errno));
  220.         return -1;
  221.     }
  222.     (void) chmod (name, 0644);    /* beware of overly restrictive umask */
  223. #ifdef HAVE_BINARY_LOCKFILES
  224.     pid = getpid ();
  225.     write (fd, &pid, sizeof (pid));
  226. #else
  227.     sprintf (filename, "%10d\n", (int)getpid ());
  228.     write (fd, filename, 11);
  229. #endif
  230.     close (fd);
  231.  
  232.     return 0;
  233. }
  234.  
  235.  
  236.  
  237. /*---------------------------------------------------------------------------*/
  238.  
  239. static char const *lockdir_paths[] = {
  240.     "/usr/spool/uucp",
  241.     "/var/spool/lock",
  242.     "/var/spool/uucp",
  243.     "/var/lock",
  244.     NULLCHAR
  245. };
  246.  
  247.  
  248. void
  249. findUnixLockdir (char *where)
  250. {
  251. int k;
  252. struct stat sb;
  253.  
  254.     if (where && !stat (where, &sb) && S_ISDIR(sb.st_mode))    {
  255.         LOCKDIR = strdup (where);
  256.         return;
  257.     }
  258.  
  259.     for (k = 0; lockdir_paths[k] != NULLCHAR; k++)    {
  260.         if (stat (lockdir_paths[k], &sb))
  261.             continue;
  262.         if (S_ISDIR(sb.st_mode))    {
  263.             LOCKDIR = lockdir_paths[k];
  264.             return;
  265.         }
  266.     }
  267.  
  268.     /* error! can't find lockdir! */
  269.     printf ("\007!! Cannot start TNOS!\nCannot locate a directory for the Lockfiles!\nThe following were searched:\n");
  270.     for (k = 0; lockdir_paths[k] != NULLCHAR; k++)
  271.         printf ("\t%s\n", lockdir_paths[k]);
  272.  
  273.     (void) fflush (stdout);
  274.     (void) sleep (5);
  275.     exit (1);
  276. }
  277.  
  278.  
  279.  
  280. /*---------------------------------------------------------------------------*/
  281.  
  282. /* Initialize asynch port "dev" */
  283. int
  284. asy_init (dev, ifp, arg1, arg2, bufsize, trigchar, monitor, speed, force, triglevel, polled)
  285. int dev;
  286. struct iface *ifp;
  287. char *arg1;        /* Attach args for address and vector */
  288. char *arg2 OPTIONAL;
  289. int16 bufsize;
  290. int trigchar OPTIONAL;
  291. char monitor OPTIONAL;
  292. long speed;
  293. int force OPTIONAL;
  294. int triglevel;
  295. int polled OPTIONAL;
  296. {
  297. register struct asy *ap;
  298. char filename[80];
  299. char *ifn;
  300. int sp, fd = 0;
  301. struct termios termios;
  302. #ifdef POLLEDKISS
  303. long interval;
  304. #endif
  305.  
  306.     ap = &Asy[dev];
  307.  
  308.     filename[0] = 0;
  309. #ifdef UNIX_SOCKETS
  310.     if (atoi (arg2)) {
  311.         struct sockaddr_in addr;
  312.         struct hostent *hp;
  313.         u_long hostaddr;
  314.  
  315.         if ((fd = socket (AF_INET, SOCK_STREAM, 0)) < 0)
  316.             goto Fail;
  317.  
  318. #if 1
  319.         hostaddr = inet_addr (arg1);
  320.         if (hostaddr != (u_long) - 1) {
  321.             addr.sin_addr.s_addr = hostaddr;
  322. #else
  323.         if (isaddr (arg1)) {
  324.             *((int32 *) & addr.sin_addr) = aton (arg1);
  325. #endif
  326.             addr.sin_family = AF_INET;
  327.         } else {
  328.             if ((hp = gethostbyname (arg1)) != NULL) {
  329.                 addr.sin_family = (short) hp->h_addrtype;
  330. #if defined(h_addr)
  331.                 memcpy ((caddr_t) & addr.sin_addr, hp->h_addr_list[0], (unsigned) hp->h_length);
  332. #else
  333.                 memcpy ((caddr_t) & addr.sin_addr, hp->h_addr, (unsigned) hp->h_length);
  334. #endif
  335.             } else {
  336.                 tprintf ("unknown host: %s\n", arg1);
  337.                 goto Fail;
  338.             }
  339.         }
  340.  
  341.         addr.sin_port = htons ((int16)atoi (arg2));
  342.  
  343.         if (connect (fd, (struct sockaddr *) &addr, sizeof (addr)) < 0)
  344.             goto Fail;
  345.  
  346.         ap->uulock[0] = '\0';
  347.         ap->fd = fd;
  348.  
  349.     } else {
  350. #endif
  351.         /* just in case the user forgot to create the lock dir */
  352.         (void) mkdir (LOCKDIR, 0777);
  353.         /* UUCP locking with ASCII pid */
  354.         sprintf (ap->uulock, "%s/LCK..%s", LOCKDIR, arg1);
  355.         if (Unixlockfile (ap->uulock, 1, arg1, 0) == -1)
  356.             goto Fail;
  357.         strcpy (filename, "/dev/");
  358.         strcat (filename, arg1);
  359.         if ((fd = open (filename, O_RDWR | O_NONBLOCK | O_NOCTTY, 0644)) == -1) {
  360.             tprintf ("Can't open port: %s\n", strerror (errno));
  361.             goto Fail;
  362.         }
  363. #ifdef UNIX_SOCKETS
  364.     }
  365. #endif
  366.     ap->flags = 0;
  367.     ap->iface = ifp;
  368.     sp = find_speed (speed);
  369.     ap->speed = speed_table[sp].speed;
  370. #ifdef UNIX_SOCKETS
  371.     if (!atoi (arg2)) {    /* it's not efficient to do this twice...bfd */
  372. #endif
  373.         memset ((char *) &termios, 0, sizeof (termios));
  374.         termios.c_iflag = IGNBRK | IGNPAR;
  375.         termios.c_cflag = CS8 | CREAD | CLOCAL | speed_table[sp].flags;
  376.         termios.c_cc[VTIME] = 2;
  377.         ap->pktsize = triglevel & 255;
  378.         if (ap->pktsize)
  379.             termios.c_cc[VMIN] = triglevel & 255;
  380.         if (cfsetispeed (&termios, speed_table[sp].flags) == -1) {
  381.             tprintf ("Can't set speed: %s\n", strerror (errno));
  382.             goto Fail;
  383.         }
  384.         if (cfsetospeed (&termios, speed_table[sp].flags) == -1) {
  385.             tprintf ("Can't set speed: %s\n", strerror (errno));
  386.             goto Fail;
  387.         }
  388.         if (tcsetattr (fd, TCSANOW, &termios) == -1) {
  389.             tprintf ("warning: Can't configure port: %s\n", strerror (errno));
  390.             /* goto Fail; *//* made this non-terminal for z8530 kernel driver */
  391.         }
  392.         /* security: port won't work until re-opened */
  393.         if (filename[0])    {
  394.             if ((ap->fd = open (filename, O_RDWR | O_NONBLOCK | O_NOCTTY, 0644)) == -1) {
  395.                 tprintf ("Can't reopen port: %s\n", strerror (errno));
  396.                 goto Fail;
  397.             }
  398.             close (fd);
  399.         }
  400.  
  401. #ifdef UNIX_SOCKETS
  402.     }
  403. #endif
  404.     /* new asy parameters, defaulted for now */
  405.     ap->rxq = 1;        /* disable queueing */
  406.     ap->txq = 1;
  407.     ap->rxbuf = bufsize;
  408. #ifdef POLLEDKISS
  409.     ap->poller = NULL;
  410. #endif
  411.  
  412.     /* clear statistics */
  413.     ap->rxints = 0;
  414.     ap->txints = 0;
  415.     ap->rxchar = 0;
  416.     ap->txchar = 0;
  417.     ap->rxput = 0;
  418.     ap->rxovq = 0;
  419.     ap->rxblock = 0;
  420.     ap->txget = 0;
  421.     ap->txovq = 0;
  422.     ap->txblock = 0;
  423.  
  424.     ifp->txproc = newproc (ifn = if_name (ifp, " tx"),
  425.                    256, asy_tx, dev, ifp, NULL, 0);
  426.     free (ifn);
  427.     ap->rxproc = newproc (ifn = if_name (ifp, " hw"),
  428.                   256, asy_input, dev, ifp, NULL, 0);
  429.     free (ifn);
  430.  
  431.     ifp->txproc->ptype = ap->rxproc->ptype = PTYPE_IO;
  432.     register_io (ap->fd, &ap->fd);
  433.  
  434. #ifdef POLLEDKISS
  435.     if (polled) {
  436.         /* Calculate the poll interval: some processing time +
  437.          * the packet duration for a mtu size packet.
  438.          */
  439.         interval = (((long) ifp->mtu * 10000L) / speed);
  440.         ap->poller = newproc (ifn = if_name (ifp, " poller"),
  441.            384, kiss_poller, ifp->xdev, (void *) interval, NULL, 0);
  442.         ap->poller->ptype = PTYPE_IO;
  443.         free (ifn);
  444.     }
  445. #endif
  446.  
  447.     return 0;
  448.  
  449. Fail:
  450.     rflush ();        /* make sure the message gets out */
  451.     if (fd != -1)
  452.         close (fd);
  453.     /* Unlock port */
  454.     if (ap->uulock[0])
  455.         unlink (ap->uulock);
  456.     ap->uulock[0] = '\0';
  457.     ap->iface = NULLIF;
  458.     return -1;
  459. }
  460.  
  461.  
  462. /*---------------------------------------------------------------------------*/
  463.  
  464. int
  465. asy_stop (struct iface *ifp)
  466. {
  467. register struct asy *ap;
  468.  
  469.     ap = &Asy[ifp->dev];
  470.  
  471.     if (ap->iface == NULLIF)
  472.         return -1;    /* Not allocated */
  473.  
  474.     unregister_io (ap->fd);
  475.  
  476. #ifdef POLLEDKISS
  477.     if (ap->poller)
  478.         killproc (ap->poller);
  479. #endif
  480.     if (ifp->txproc)
  481.         killproc (ifp->txproc);
  482.     ifp->txproc = 0;
  483.  
  484.     if (ap->rxproc)
  485.         killproc (ap->rxproc);
  486.     ap->rxproc = 0;
  487.  
  488.     ap->iface = NULLIF;
  489.  
  490.     free_q (&ap->sndq);
  491.     close (ap->fd);
  492.  
  493.     free_q (&ap->rcvq);
  494.  
  495.     if (ap->uulock[0])
  496.         unlink (ap->uulock);
  497.     ap->uulock[0] = '\0';
  498.  
  499.     return 0;
  500. }
  501.  
  502.  
  503. void
  504. detach_all_asy ()
  505. {
  506. register struct asy *ap;
  507.  
  508.     for (ap = Asy; ap != Asy + ASY_MAX; ap++) {
  509.         if (ap->iface == NULLIF)
  510.             break;
  511.         unregister_io (ap->fd);
  512.         if (ap->iface->txproc)
  513.             killproc (ap->iface->txproc);
  514.         ap->iface->txproc = 0;
  515.         if (ap->rxproc)
  516.             killproc (ap->rxproc);
  517.         ap->rxproc = 0;
  518.         ap->iface = NULLIF;
  519.         free_q (&ap->sndq);
  520.         free_q (&ap->rcvq);
  521.         close (ap->fd);
  522.         if (ap->uulock[0])
  523.             unlink (ap->uulock);
  524.         ap->uulock[0] = '\0';
  525.     }
  526. }
  527.  
  528.  
  529. /*---------------------------------------------------------------------------*/
  530.  
  531. /* Set asynch line speed */
  532. int
  533. asy_speed (int dev, long bps)
  534. {
  535. struct asy *asyp;
  536. int sp;
  537. struct termios termios;
  538.  
  539.     if (bps <= 0 || dev >= ASY_MAX)
  540.         return -1;
  541.     asyp = &Asy[dev];
  542.     if (asyp->iface == NULLIF)
  543.         return -1;
  544.     if (bps == 0)
  545.         return -1;
  546.     sp = find_speed (bps);
  547.     if (tcgetattr (asyp->fd, &termios))
  548.         return -1;
  549.     if (cfsetispeed (&termios, speed_table[sp].flags))
  550.         return -1;
  551.     if (cfsetospeed (&termios, speed_table[sp].flags))
  552.         return -1;
  553. #if 0    /* was !defined(linux) && !defined(BSD) && !defined(__FreeBSD__)    This is obsolete stuff! */
  554.     termios.c_cflag &= ~CBAUD;
  555.     termios.c_cflag |= speed_table[sp].flags;
  556. #endif
  557.     if (tcsetattr (asyp->fd, TCSANOW, &termios))
  558.         return -1;
  559.     asyp->speed = speed_table[sp].speed;
  560.     return 0;
  561. }
  562.  
  563.  
  564. /* Set termios VMIN (packet size) */
  565. static int
  566. asy_vmin (int dev, long pktsize)
  567. {
  568. struct termios termios;
  569. struct asy *asyp;
  570.  
  571.     if (pktsize < 0 || pktsize > 255 || dev >= ASY_MAX)
  572.         return -1;
  573.     if ((asyp = &Asy[dev])->iface == NULLIF)
  574.         return -1;
  575.     if (tcgetattr (asyp->fd, &termios))
  576.         return -1;
  577.     termios.c_cc[VMIN] = asyp->pktsize = pktsize & 255;
  578.     if (tcsetattr (asyp->fd, TCSANOW, &termios))
  579.         return -1;
  580.     return 0;
  581. }
  582.  
  583.  
  584. /* Set or clear RTS/CTS flow control */
  585. static int
  586. asy_rts (int dev, unsigned long onoff)
  587. {
  588. struct termios termios;
  589. struct asy *asyp;
  590.  
  591.     if ((asyp = &Asy[dev])->iface == NULLIF)
  592.         return -1;
  593.     if (tcgetattr (asyp->fd, &termios))
  594.         return -1;
  595.     /*
  596.      * note sense is reversed as per DOS version, except that we default to
  597.      * RTS/CTS being *off* for compatibility with earlier ALPHA versions
  598.      */
  599.     if (onoff) {
  600.         asyp->flags &= ~ASY_RTSCTS;
  601.         termios.c_cflag &= ~((tcflag_t) TNOS_CRTSCTS);    /*lint !e40 */
  602.     } else {
  603.         asyp->flags |= ASY_RTSCTS;
  604.         termios.c_cflag |= ((tcflag_t) TNOS_CRTSCTS);    /*lint !e40 */
  605.     }
  606.     if (tcsetattr (asyp->fd, TCSANOW, &termios))
  607.         return -1;
  608.     return 0;
  609. }
  610.  
  611.  
  612. /*---------------------------------------------------------------------------*/
  613.  
  614. /* Asynchronous line I/O control */
  615. int32
  616. asy_ioctl (struct iface * ifp, int cmd, int set, int32 val)
  617. {
  618. struct asy *ap = &Asy[ifp->dev];
  619.  
  620.     switch (cmd) {
  621.         case PARAM_SPEED:
  622.             if (set)
  623.                 (void) asy_speed (ifp->dev, val);
  624.             return ap->speed;
  625.         case PARAM_MIN:
  626.             if (set)
  627.                 (void) asy_vmin (ifp->dev, val);
  628.             return ap->pktsize;
  629.         case PARAM_RTS:
  630.             if (set)
  631.                 (void) asy_rts (ifp->dev, (unsigned long) val);
  632.             return (ap->flags & ASY_RTSCTS) == 0;
  633.         default:
  634.             break;
  635.     }
  636.     return -1;
  637. }
  638.  
  639.  
  640. /*---------------------------------------------------------------------------*/
  641.  
  642. static void
  643. asy_input (int dev, void *arg1 OPTIONAL, void *arg2 OPTIONAL)
  644. {
  645. struct timeval tv;
  646. struct asy *ap;
  647. fd_set fds;
  648. char *buf;
  649. int i, c;
  650.  
  651.     server_disconnect_io ();
  652.     ap = &Asy[dev];
  653.     for (;;) {
  654.         if (kwait (&ap->fd) != 0)
  655.             return;
  656.         ap->rxints++;
  657.         buf = mallocw (ap->rxbuf);
  658.  
  659.         if (ap->pktsize)
  660.             (void) fcntl (ap->fd, F_SETFL, fcntl (ap->fd, F_GETFL, 0) & ~O_NONBLOCK);
  661.         if ((i = read (ap->fd, buf, ap->rxbuf)) == 0 || (!ap->pktsize && i == -1 && errno == EWOULDBLOCK)) {
  662.             if (ap->pktsize)
  663.                 (void) fcntl (ap->fd, F_SETFL, fcntl (ap->fd, F_GETFL, 0) | O_NONBLOCK);
  664.             ap->rxblock++;
  665.             free (buf);
  666.             continue;
  667.         }
  668.  
  669.         if (i == -1) {
  670.             if (errno == EINTR || errno == ECHILD) {
  671. #if 0
  672.                 tprintf ("asy_input(%d): read interrupted, retrying.\n", dev);
  673. #endif
  674.                 continue;
  675.             }
  676.             tprintf ("asy_input(%d): read error %d, shutting down\n", dev,
  677.                  errno);
  678.             if (ap->pktsize)
  679.                 (void) fcntl (ap->fd, F_SETFL, fcntl (ap->fd, F_GETFL, 0) | O_NONBLOCK);
  680.             free (buf);
  681.             return;
  682.         }
  683.         if ((c = ap->rxq) <= 0)
  684.             c = 1;
  685.         while (i > 0 && c > 0) {
  686.             ap->rxchar += (uint32) i;
  687.             ap->rxput++;
  688.             enqueue (&ap->rcvq, qdata ((unsigned char *) buf, (int16) i));
  689.             c--;
  690.             if (ap->pktsize) {
  691.                 /* can't just read to check for data, since it might block */
  692. #ifndef _lint
  693.                 FD_ZERO (&fds);
  694.                 FD_SET (ap->fd, &fds);
  695. #endif
  696.                 tv.tv_sec = tv.tv_usec = 0;
  697.                 if (select (FD_SETSIZE, &fds, 0, 0, &tv) == 0) {
  698.                     i = -1;
  699.                     errno = EWOULDBLOCK;
  700.                     break;
  701.                 }
  702.             }
  703.             i = read (ap->fd, buf, ap->rxbuf);
  704.         }
  705.         free (buf);
  706.         if (i == -1 && (errno == EINTR || errno == ECHILD)) {
  707. #if 0
  708.             tprintf ("asy_input(%d): read interrupted, retrying.\n", dev);
  709. #endif
  710.             continue;
  711.         }
  712.         if (i == -1 && errno != EWOULDBLOCK) {
  713.             tprintf ("asy_input(%d): read error %d, shutting down\n", dev,
  714.                  errno);
  715.             return;
  716.         }
  717.         if (ap->pktsize)
  718.             (void) fcntl (ap->fd, F_SETFL, fcntl (ap->fd, F_GETFL, 0) | O_NONBLOCK);
  719.         if (c < 1 && ap->rxq > 1)
  720.             ap->rxovq++;
  721.     }
  722. }
  723.  
  724.  
  725. int
  726. get_asy (int dev)
  727. {
  728. #if 0
  729. struct asy *ap;
  730.  
  731.     ap = &Asy[dev];
  732.     if (ap->iface == NULLIF)
  733.         return -1;
  734.     while (!ap->rcvq) {
  735.         if (kwait (&ap->rcvq) != 0)
  736.             return -1;    /* may not be dead, e.g. alarm in dialer */
  737.     }
  738.     ap = &Asy[dev];
  739.     return PULLCHAR (&ap->rcvq);
  740. #else
  741.     if (Asy[dev].iface == NULLIF)
  742.         return -1;
  743.     if (!Asy[dev].rcvq)    {
  744.         do    {
  745.             if (kwait (&Asy[dev].rcvq) != 0)
  746.                 return -1;    /* may not be dead, e.g. alarm in dialer */
  747.         
  748.         } while (!Asy[dev].rcvq);
  749.     }
  750.     return PULLCHAR (&Asy[dev].rcvq);
  751.  
  752. #endif
  753.  
  754. }
  755.  
  756.  
  757. /*---------------------------------------------------------------------------*/
  758.  
  759. void
  760. pasy (struct asy *asyp)
  761. {
  762.     tprintf ("%s: %lu bps, ", asyp->iface->name, asyp->speed);
  763.     if (asyp->pktsize)
  764.         tprintf ("packet size %d", asyp->pktsize);
  765.     else
  766.         tputs ("non-blocking");
  767.     tprintf (", RTS/CTS %sabled", (asyp->flags & ASY_RTSCTS ? "en" : "dis"));
  768. #if 0
  769.     tprintf (", carrier %sabled", (asyp->flags & ASY_CARR ? "en" : "dis"));
  770. #endif
  771.     tprintf ("\n  RX: ints %lu chars %lu puts %lu buf %d rxqueue %d qlen %d ovq "
  772.          "%ld block %ld\n",
  773.         asyp->rxints, asyp->rxchar, asyp->rxput, asyp->rxbuf, asyp->rxq,
  774.          len_q (asyp->rcvq), asyp->rxovq, asyp->rxblock);
  775.     tprintf ("  TX: ints %lu gets %lu chars %lu txqueue %d qlen %d ovq %ld "
  776.          "block %ld\n",
  777.          asyp->txints, asyp->txget, asyp->txchar, asyp->txq,
  778.          len_q (asyp->sndq), asyp->txovq, asyp->txblock);
  779. }
  780.  
  781.  
  782. /*---------------------------------------------------------------------------*/
  783.  
  784. /* Serial transmit process, common to all protocols */
  785.  
  786. /*
  787.  * Yes, this badly needs to be rewritten.
  788.  */
  789.  
  790. static void
  791. asy_tx (int dev, void *p1 OPTIONAL, void *p2 OPTIONAL)
  792. {
  793. register struct mbuf *bp;
  794. struct asy *asyp;
  795. int c, l, off;
  796.  
  797.     server_disconnect_io ();
  798.     asyp = &Asy[dev];
  799.     if ((c = asyp->txq) <= 0)
  800.         c = 1;
  801.     for (;;) {
  802.         while (asyp->sndq == NULLBUF) {
  803.             c = asyp->txq;
  804.             if (!c)
  805.                 c = 1;
  806.             if (kwait (&asyp->sndq) != 0)
  807.                 return;
  808.             asyp->txints++;
  809.         }
  810.         bp = dequeue (&asyp->sndq);
  811.         asyp->txget++;
  812.         off = 0;
  813.         while (bp != NULLBUF) {
  814.             l = write (asyp->fd, bp->data + off, (size_t) bp->cnt - (int16) off);
  815.             if (l == -1 && (errno == EINTR || errno == ECHILD)) {
  816. #if 0
  817.                 tprintf ("asy_tx(%d): write interrupted, retrying.\n", dev);
  818. #endif
  819.                 continue;
  820.             }
  821.             if (l == -1 && errno != EWOULDBLOCK) {
  822.                 tprintf ("asy_tx(%d): write error %d, shutting down\n", dev,
  823.                      errno);
  824.                 return;
  825.             }
  826.             if (l == -1)
  827.                 l = 0;
  828.             asyp->txchar += (uint32) l;
  829.             if (l == bp->cnt - off) {
  830.                 bp = free_mbuf (bp);
  831.                 off = 0;
  832.             } else {
  833.                 asyp->txblock++;
  834.                 kwait (NULL);
  835.                 off += l;
  836.             }
  837.         }
  838.         if (--c < 1 && asyp->txq > 1) {
  839.             asyp->txovq++;
  840.             kwait (NULL);
  841.         }
  842.     }
  843. }
  844.  
  845.  
  846. /*---------------------------------------------------------------------------*/
  847.  
  848. /* Send a message on the specified serial line */
  849. int
  850. asy_send (int dev, struct mbuf *bp)
  851. {
  852. struct asy *asyp;
  853.  
  854.     if (dev < 0 || dev >= ASY_MAX) {
  855.         free_p (bp);
  856.         return -1;
  857.     }
  858.     asyp = &Asy[dev];
  859.  
  860.     if (asyp->iface == NULLIF)
  861.         free_p (bp);
  862.     else
  863.         enqueue (&asyp->sndq, bp);
  864.     return 0;
  865. }
  866.  
  867.  
  868. /* stub, CD not enabled at present */
  869.  
  870. int
  871. carrier_detect (int dev OPTIONAL)
  872. {
  873.     return 1;        /* assume always on, with CLOCAL it is! */
  874. }
  875.  
  876.  
  877. /*---------------------------------------------------------------------------*/
  878.  
  879. int
  880. doasyconfig (int ac, char **av, void *p OPTIONAL)
  881. {
  882. struct iface *ip;
  883. struct asy *ap;
  884. int k;
  885.  
  886.     if (ac < 3)
  887.         return 1;
  888.     ip = if_lookup (av[1]);
  889.     if (!ip) {
  890.         tprintf ("Interface %s unknown\n", av[1]);
  891.         return 1;
  892.     }
  893.     for (k = 0, ap = Asy; k < ASY_MAX; ap++) {
  894.         if (ap->iface == ip)
  895.             break;
  896.     }
  897.     if (k == ASY_MAX || !ap) {
  898.         tprintf ("Interface %s not asy\n", av[1]);
  899.         return 1;
  900.     }
  901.     return subcmd (AsyPcmds, ac - 1, av + 1, ap);
  902. }
  903.  
  904.  
  905. static int
  906. doasy2stat (int ac OPTIONAL, char **av OPTIONAL, void *d)
  907. {
  908.     pasy ((struct asy *) d);
  909.     return 0;
  910. }
  911.  
  912.  
  913. static int
  914. dorxqueue (int ac, char **av, void *d)
  915. {
  916.     return setint (&((struct asy *) d)->rxq, "Receive queue size", ac, av);
  917. }
  918.  
  919.  
  920. static int
  921. dotxqueue (int ac, char **av, void *d)
  922. {
  923.     return setint (&((struct asy *) d)->txq, "Transmit queue size", ac, av);
  924. }
  925.  
  926.  
  927. static int
  928. dobufsize (int ac, char **av, void *d)
  929. {
  930.     return setuns (&((struct asy *) d)->rxbuf, "Receive buffer size", ac, av);
  931. }
  932.  
  933. #endif        /* UNIX */
  934.